package com.shopping.common.redis.config;


import cn.hutool.core.util.ArrayUtil;
import com.shopping.common.core.exception.InvalidRedisModeException;
import jodd.util.StringUtil;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConditionalOnProperty(name = "redis.redisson.enabled",havingValue = "true")
public class RedissonConfig {

    @Value("${redis.redisson.lockWatchdogTimeout}")
    private Integer lockWatchdogTimeout;

    @Value("${redis.redisson.mode}")
    private String mode;

    /**
     * 仅仅用于sentinel模式
     */
    @Value("${redis.redisson.masterName}")
    private String masterName;

    @Value("${redis.redisson.address}")
    private String address;

    @Value("${redis.redisson.timeout}")
    private Integer timeout;

    @Value("${redis.redisson.password}")
    private String password;

    @Value("${redis.redisson.pool.poolSize}")
    private Integer poolSize;

    @Value("${redis.redisson.pool.minIdle}")
    private Integer minIdle;

    @Bean
    public RedissonClient redissonClient(){
        if(StringUtil.isBlank(password)){
            password = null;
        }
        Config config = new Config();
        if("single".equals(mode)){
            config.setLockWatchdogTimeout(lockWatchdogTimeout)
                    .useSingleServer()
                    .setAddress(address)
                    .setConnectionPoolSize(poolSize)
                    .setConnectionMinimumIdleSize(minIdle)
                    .setConnectTimeout(timeout);
        }else if("cluster".equals(mode)){
            String[] clusterAddress = address.split(",");
            config.setLockWatchdogTimeout(lockWatchdogTimeout)
                    .useClusterServers()
                    .setPassword(password)
                    .addNodeAddress(clusterAddress)
                    .setConnectTimeout(timeout)
                    .setMasterConnectionPoolSize(poolSize)
                    .setMasterConnectionMinimumIdleSize(minIdle);
        }else if("sentinel".equals(mode)){
            String[] sentinelAddress = address.split(",");
            config.setLockWatchdogTimeout(lockWatchdogTimeout)
                    .useSentinelServers()
                    .setPassword(password)
                    .setMasterName(masterName)
                    .addSentinelAddress(sentinelAddress)
                    .setConnectTimeout(timeout)
                    .setMasterConnectionPoolSize(poolSize)
                    .setMasterConnectionMinimumIdleSize(minIdle);
        }else if("master-slave".equals(mode)){
            String[] masterSlaveAddress = address.split(",");
            if(masterSlaveAddress.length == 1){
                throw new IllegalArgumentException (
                    "redis.redisson.address MUST have multiple redis address for master-slave mode.");
            }
            String[] slaveAddress = new String[masterSlaveAddress.length - 1];
            ArrayUtil.copy(masterSlaveAddress,1,slaveAddress,0,slaveAddress.length);
            config.setLockWatchdogTimeout(lockWatchdogTimeout)
                    .useMasterSlaveServers()
                    .setPassword(password)
                    .setMasterAddress(masterSlaveAddress[0])
                    .addSlaveAddress(slaveAddress)
                    .setConnectTimeout(timeout)
                    .setMasterConnectionPoolSize(poolSize)
                    .setMasterConnectionMinimumIdleSize(minIdle);
        }else {
            throw new InvalidRedisModeException(mode);
        }
        return Redisson.create(config);
    }
}
